package 行为型模式

import java.io.File
import java.nio.file.*
import java.nio.file.attribute.BasicFileAttributes

/**
 * 表示一个作用于某对象结构中的各元素的操作。
 * 它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作
 */
interface Visitor {
    fun visitDir(dir: File)
    fun visitFile(file: File)
}

class FileStructure(private val path: File) {
    fun handle(visitor: Visitor) {
        scan(path, visitor)
    }

    private fun scan(file: File, visitor: Visitor) {
        if (file.isDirectory) {
            // 让访问者处理文件夹:
            visitor.visitDir(file)
            for (sub in file.listFiles()!!) {
                // 递归处理子文件夹:
                scan(sub, visitor)
            }
        } else if (file.isFile) {
            // 让访问者处理文件:
            visitor.visitFile(file)
        }
    }
}

class JavaFileVisitor : Visitor {
    override fun visitDir(dir: File) {
        println("Visit dir: $dir")
    }

    override fun visitFile(file: File) {
        if (file.name.endsWith(".java")) {
            println("Found java file: $file")
        }
    }
}

class ClassFileCleanerVisitor : Visitor {
    override fun visitDir(dir: File) {}
    override fun visitFile(file: File) {
        if (file.name.endsWith(".class")) {
            println("Will clean class file: $file")
        }
    }
}

/**
 * 访问者模式的核心思想是为了访问比较复杂的数据结构，不去改变数据结构，而是把对数据的操作抽象出来，
 * 在"访问"的过程中以回调形式在访问者中处理操作逻辑。如果要新增一组操作，那么只需要增加一个新的访问者。
 */

fun main() {
    val fs = FileStructure(File("."))
    fs.handle(JavaFileVisitor())

    //Files.walkFileTree(Paths.get("."), MyFileVisitor())
}


class MyFileVisitor : SimpleFileVisitor<Path>() {
    override fun preVisitDirectory(dir: Path?, attrs: BasicFileAttributes?): FileVisitResult {
        println("pre visit dir: $dir")
        return FileVisitResult.CONTINUE
    }

    override fun visitFile(file: Path?, attrs: BasicFileAttributes?): FileVisitResult {
        println("visit file: $file");
        // 返回CONTINUE表示继续访问:
        return FileVisitResult.CONTINUE
    }

}